home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / CONVERS.C < prev    next >
Text File  |  1993-08-09  |  21KB  |  875 lines

  1. /* convers server - based on conversd written by DK5SG
  2.  * ported to WNOS by DB3FL - 9109xx/9110xx
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include <ctype.h>
  9. #include <io.h>
  10. #include "global.h"
  11. #include "config.h"
  12. #ifdef CONVERS
  13. #ifdef MAILBOX
  14. #include "mailbox.h"
  15. #include "netuser.h"
  16. #endif
  17. #include "timer.h"
  18. #include "smtp.h"
  19. #include "cmdparse.h"
  20. #include "socket.h"
  21. #include "session.h"
  22. #include "files.h"
  23. #include "clients.h"
  24. #include "convers.h"
  25. #ifdef LZW
  26. #include "lzw.h"
  27. #endif
  28.  
  29. char *CHostname = NULLCHAR;
  30. static char near cnumber[] = "*** Channel numbers must be in the range 0..%d.\n";
  31.  
  32. #define MAXCHANNEL         32766
  33. #define LINELEN            256
  34. #define CBUFLEN            2048
  35. #define MAX_WAITTIME    (3 * HOURS)
  36.  
  37. struct convection {
  38.   int  type;                    /* Connection type */
  39. #define CT_UNKNOWN      0
  40. #define CT_USER         1
  41. #define CT_HOST         2
  42. #define CT_CLOSED       3
  43.   char  name[80];                  /* Name of user or host */
  44.   char  host[80];                /* Name of host where user is logged on */
  45.   struct convection *via;       /* Pointer to neighbor host */
  46.   int  channel;                 /* Channel number */
  47.   int32 time;                   /* Connect time */
  48.   int  locked;                  /* Set if mesg already sent */
  49.   int  fd;                        /* Socket descriptor */
  50.   char  *ibuf;                    /* Input buffer */
  51.   int32  received;                /* Number of bytes received */
  52.   int32  xmitted;                 /* Number of bytes transmitted */
  53.   struct convection *next;      /* Linked list pointer */
  54. };
  55.  
  56. #define CM_UNKNOWN   (1 << CT_UNKNOWN)
  57. #define CM_USER      (1 << CT_USER)
  58. #define CM_HOST      (1 << CT_HOST)
  59. #define CM_CLOSED    (1 << CT_CLOSED)
  60.  
  61. #define NULLCONNECTION  ((struct convection *) 0)
  62.  
  63. static struct convection *convections = NULLCONNECTION;
  64.  
  65. struct permlink *Permlink = NULLPERMLINK;
  66.  
  67. static char * near
  68. getarg(char *line,int all)
  69. {
  70.   char *arg;
  71.   static char *cp;
  72.  
  73.   if (line) {
  74.     for (cp = line; *cp; cp++) ;
  75.     while (--cp >= line && isspace(*cp & 0xff)) ;
  76.     cp[1] = 0;
  77.     cp = line;
  78.   }
  79.   while (isspace(*cp & 0xff)) cp++;
  80.   if (all) return cp;
  81.   arg = cp;
  82.   while (*cp && !isspace(*cp & 0xff)) {
  83.     if (*cp >= 'A' && *cp <= 'Z') *cp = tolower(*cp);
  84.     cp++;
  85.   }
  86.   if (*cp) *cp++ = 0;
  87.   return arg;
  88. }
  89.  
  90. static void near
  91. free_connection(struct convection *cp)
  92. {
  93.   struct permlink *p;
  94.  
  95.   for (p = Permlink; p; p = p->next)
  96.     if (p->convection == cp)
  97.       p->convection = NULLCONNECTION;
  98.   if (cp->fd)
  99.     close_s(cp->fd);
  100.   xfree(cp->ibuf);
  101.   xfree(cp);
  102. }
  103.  
  104. static void near
  105. free_closed_connections(void)
  106. {
  107.   struct convection *cp, *p;
  108.  
  109.   for (p = NULLCONNECTION, cp = convections; cp; )
  110.     if (cp->type == CT_CLOSED
  111.      || cp->type == CT_UNKNOWN
  112.      && cp->time + 300 < currtime) {
  113.       if (p) {
  114.         p->next = cp->next;
  115.         free_connection(cp);
  116.         cp = p->next;
  117.       } else {
  118.         convections = cp->next;
  119.         free_connection(cp);
  120.         cp = convections;
  121.       }
  122.     } else {
  123.       p = cp;
  124.       cp = cp->next;
  125.     }
  126. }
  127.  
  128. static void near
  129. update_Permlink(char *name,struct convection *cp)
  130. {
  131.   struct permlink *p;
  132.  
  133.   for(p = Permlink; p; p = p->next)
  134.     if(!strcmp(p->name, name)) {
  135.       p->convection = cp;
  136.       p->statetime = currtime;
  137.       p->tries = 0;
  138.       p->waittime = 60;
  139.       p->retrytime = currtime + p->waittime;
  140.     }
  141. }
  142.  
  143. static struct convection * near
  144. alloc_connection(int fd)
  145. {
  146.   struct convection *cp = mxallocw(sizeof(struct convection));
  147.  
  148.   cp->next = convections;
  149.   convections = cp;
  150.  
  151.   cp->fd = fd;
  152.   cp->time = currtime;
  153.   cp->ibuf = mxallocw(CBUFLEN);
  154.   return cp;
  155. }
  156.  
  157. #ifdef LINK
  158. void
  159. connect_Permlink(int a,void *b,void *c)
  160. {
  161.   FILE *fp;
  162.   char *cp, line[LINELEN];
  163.   struct permlink *p;
  164.  
  165.   if(CHostname == NULLCHAR) {
  166.     CHostname = strxdup(Hostname);
  167.     if((cp = strchr(CHostname,'.')) != NULLCHAR) {
  168.       *cp = '\0';
  169.     }
  170.   }
  171.  
  172.   sprintf(line,"%s/convers.cfg",EtcRoot);
  173.  
  174.   if((fp = Fopen(line,READ_TEXT,0,0)) != NULLFILE) {
  175.     while(fgets(line,LINELEN,fp)) {
  176.       if(*line == '#') {
  177.         continue;
  178.       }
  179.       p = mxallocw(sizeof(struct permlink));
  180.  
  181.       sscanf(line,"%38s %18s %18s",p->name,p->link_info,p->command);
  182.  
  183.       if(*p->link_info) {
  184.         p->next = Permlink;
  185.         Permlink = p;
  186.       } else {
  187.         xfree(p);
  188.       }
  189.     }
  190.     Fclose(fp);
  191.   }
  192.   if(Permlink) {
  193.     int s, x;
  194.     struct sockaddr_in cport;
  195.  
  196.     for(;;) {
  197.       pause(2000L);
  198.       for (p = Permlink; p; p = p->next) {
  199.         if (p->convection || p->retrytime > currtime) continue;
  200.         p->tries++;
  201.         p->waittime <<= 1;
  202.         if (p->waittime > MAX_WAITTIME) p->waittime = MAX_WAITTIME;
  203.         p->retrytime = p->waittime + currtime;
  204.         x = 0;
  205.  
  206.         switch(tolower(*p->link_info)) {
  207.         case 'x':                            /* compressed telnet connection */
  208.           x = 1;
  209.         case 't':                            /* telnet connection */
  210.           cport.sin_family = AF_INET;
  211.           cport.sin_port = x ? IPPORT_XCONVERS : IPPORT_CONVERS;
  212.           if((cport.sin_addr.s_addr = resolve(p->name)) != 0) {
  213.             if((s = socket(AF_INET,SOCK_STREAM,0)) != -1) {
  214.               if(connect(s,(char *)&cport,SOCKSIZE) != -1) {
  215.                 p->fd = s;
  216.                 sockmode(p->fd,SOCK_BINARY);
  217.                 newproc("permlink",2048,conv_incom,s,(void *)x,NULL,0);
  218.               } else {
  219.                 close_s(s);
  220.               }
  221.             }
  222.           }
  223.           break;
  224. /*        case 'a':                               ax25 connection   */
  225. /*        case 'n':                               netrom connection */
  226. /*        default:                                                 */
  227. /*          continue;                                             */
  228.         }
  229.       }
  230.     }
  231.   }
  232. }
  233. #endif
  234.  
  235. static void near
  236. clear_locks(void)
  237. {
  238.   struct convection *p;
  239.  
  240.   for (p = convections; p; p = p->next) p->locked = 0;
  241. }
  242.  
  243. static void
  244. send_user_change_msg(char *name,char *host,int oldchannel,int newchannel)
  245. {
  246.   struct convection *p;
  247.  
  248.   for (p = convections; p; p = p->next) {
  249.     if (p->type == CT_USER && !p->via && !p->locked) {
  250.       if (p->channel == oldchannel) {
  251.         if (newchannel >= 0)
  252.           p->xmitted += usprintf(p->fd, "*** %s switched to channel %d.\n", name, newchannel);
  253.         else
  254.           p->xmitted += usprintf(p->fd, "*** %s signed off.\n", name);
  255.         p->locked = 1;
  256.       }
  257.       if (p->channel == newchannel) {
  258.         p->xmitted += usprintf(p->fd, "*** %s signed on.\n", name);
  259.         p->locked = 1;
  260.       }
  261.     }
  262.     if (p->type == CT_HOST && !p->locked) {
  263.       p->xmitted += usprintf(p->fd,"/\377\200USER %s %s 0 %d %d\n",
  264.         name, host, oldchannel, newchannel);
  265.       p->locked = 1;
  266.     }
  267.   }
  268.   return;
  269. }
  270.  
  271. static char * near
  272. timestring(int32 gmt)
  273. {
  274.   static char buffer[10];
  275.   struct tm *tm = localtime(&gmt);
  276.  
  277.   if (gmt + 86400L > currtime) {
  278.     sprintf(buffer," %2d:%02d",tm->tm_hour,tm->tm_min);
  279.   } else {
  280.     sprintf(buffer,"%-3.3s %2d",Months[tm->tm_mon - 1],tm->tm_mday);
  281.   }
  282.   return buffer;
  283. }
  284.  
  285. static char *
  286. formatline(char *prefix,char *text)
  287. {
  288. #define PREFIXLEN 10
  289. #define CONVLINELEN   79
  290.  
  291.   char  *f, *t, *x;
  292.   static char buf[2048];
  293.   int  l, lw;
  294.  
  295.   for (f = prefix, t = buf; *f; *t++ = *f++) ;
  296.   l = (int)(t - buf);
  297.   f = text;
  298.  
  299.   for (; ; ) {
  300.     while (isspace(uchar(*f))) f++;
  301.     if (!*f) {
  302.       *t++ = '\n';
  303.       *t = '\0';
  304.       return buf;
  305.     }
  306.     for (x = f; *x && !isspace(uchar(*x)); x++) ;
  307.     lw = (int)(x - f);
  308.     if (l > PREFIXLEN && l + 1 + lw > CONVLINELEN) {
  309.       *t++ = '\n';
  310.       l = 0;
  311.     }
  312.     do {
  313.       *t++ = ' ';
  314.       l++;
  315.     } while (l < PREFIXLEN);
  316.     while (lw--) {
  317.       *t++ = *f++;
  318.       l++;
  319.     }
  320.   }
  321. }
  322.  
  323. static void
  324. send_msg_to_user(char *fromname,char *toname,char *text)
  325. {
  326.   struct convection *p;
  327.   char *buffer = mxallocw(CBUFLEN);
  328.  
  329.   for (p = convections; p; p = p->next) {
  330.     if (p->type == CT_USER && !strcmp(p->name, toname))
  331.       if (p->via) {
  332.         if (!p->via->locked) {
  333.           p->via->xmitted += usprintf(p->via->fd,
  334.             "/\377\200UMSG %s %s %s\n", fromname, toname, text);
  335.           p->via->locked = 1;
  336.         }
  337.       } else {
  338.         if (!p->locked) {
  339.           if (strcmp(fromname, "conversd")) {
  340.             sprintf(buffer, "<*%s*>:", fromname);
  341.             p->xmitted += usprintf(p->fd,"%s",formatline(buffer, text));
  342.         } else {
  343.             p->xmitted += usprintf(p->fd,"%s\n",text);
  344.         }
  345.       p->locked = 1;
  346.       }
  347.     }
  348.   }
  349.   xfree(buffer);
  350.   return;
  351. }
  352.  
  353. static void
  354. send_msg_to_channel(char *fromname,int channel,char *text)
  355. {
  356.   struct convection *p;
  357.   char *buffer = mxallocw(CBUFLEN);
  358.  
  359.   for (p = convections; p; p = p->next) {
  360.     if (p->type == CT_USER && p->channel == channel) {
  361.       if (p->via) {
  362.         if (!p->via->locked) {
  363.           p->via->xmitted += usprintf(p->via->fd,
  364.             "/\377\200CMSG %s %d %s\n", fromname, channel, text);
  365.           p->via->locked = 1;
  366.         }
  367.       } else {
  368.         if (!p->locked) {
  369.           sprintf(buffer, "<%s>:", fromname);
  370.           p->xmitted += usprintf(p->fd,"%s",formatline(&buffer[0],text));
  371.           p->locked = 1;
  372.         }
  373.       }
  374.     }
  375.   }
  376.   xfree(buffer);
  377.   return;
  378. }
  379.  
  380. static void
  381. send_invite_msg(char *fromname,char *toname,int channel)
  382. {
  383.   static char invitetext[] = "\n\007\007*** Message from %s at%s ...\nPlease join convers channel %d.\n\007\007\n";
  384.   static char responsetext[] = "*** Invitation sent to %s @ %s";
  385.   static char cnvd[] = "conversd";
  386.  
  387.   char *buffer = mxallocw(CBUFLEN);
  388.  
  389.   struct convection *p;
  390. #ifdef MAILBOX
  391.   struct mbx *m;
  392. #endif
  393.  
  394.   for (p = convections; p; p = p->next) {
  395. #ifdef MAILBOX
  396.     for(m = Mbox; m != NULLMBX; m = m->next) {
  397.         if(m->state == MBX_CMD && !strcmp(m->name,toname)) {
  398.           p->xmitted += usprintf(m->user,invitetext,fromname,timestring(currtime), channel);
  399.           usflush(m->user);
  400.           clear_locks();
  401.           sprintf(buffer, responsetext, toname, "LocBBS@");
  402.           strcat(buffer,CHostname);
  403.           send_msg_to_user(cnvd, fromname, buffer);
  404.           xfree(buffer);
  405.           return;
  406.         }
  407.     }
  408. #endif
  409.     if (p->type == CT_USER && !strcmp(p->name, toname)) {
  410.       if (p->channel == channel) {
  411.         clear_locks();
  412.         sprintf(buffer, "*** User %s is already on this channel.", toname);
  413.         send_msg_to_user(cnvd, fromname, buffer);
  414.         xfree(buffer);
  415.         return;
  416.       }
  417.       if (!p->via && !p->locked) {
  418.         p->xmitted += usprintf(p->fd,invitetext,fromname,timestring(currtime),channel);
  419.         clear_locks();
  420.         sprintf(buffer, responsetext, toname, CHostname);
  421.         send_msg_to_user(cnvd, fromname, buffer);
  422.         xfree(buffer);
  423.         return;
  424.       }
  425.       if (p->via && !p->via->locked) {
  426.         p->via->xmitted += usprintf(p->via->fd,
  427.           "/\377\200INVI %s %s %d\n", fromname, toname, channel);
  428.         xfree(buffer);
  429.         return;
  430.       }
  431.     }
  432.   }
  433.   for (p = convections; p; p = p->next) {
  434.     if (p->type == CT_HOST && !p->locked) {
  435.       p->xmitted += usprintf(p->fd,
  436.         "/\377\200INVI %s %s %d\n", fromname, toname, channel);
  437.     }
  438.   }
  439.   xfree(buffer);
  440.   return;
  441. }
  442.  
  443. static void near
  444. bye_command(struct convection *cp)
  445. {
  446.   struct convection *p;
  447.  
  448.   int oldtype = cp->type;
  449.   cp->type = CT_CLOSED;
  450.  
  451.   switch(oldtype) {
  452.   case CT_USER:
  453.     clear_locks();
  454.     send_user_change_msg(cp->name,cp->host,cp->channel,-1);
  455.     break;
  456.   case CT_HOST:
  457.     update_Permlink(cp->name, NULLCONNECTION);
  458.     for (p = convections; p; p = p->next) {
  459.       if (p->via == cp) {
  460.         p->type = CT_CLOSED;
  461.         clear_locks();
  462.         send_user_change_msg(p->name,p->host,p->channel,-1);
  463.       }
  464.     }
  465.     break;
  466.   }
  467. }
  468.  
  469. static void near
  470. channel_command(struct convection *cp)
  471. {
  472.   int newchannel;
  473.  
  474.   char *s = getarg(0,0);
  475.  
  476.   if (!*s) {
  477.     cp->xmitted += usprintf(cp->fd,"*** You are on channel %d.\n",cp->channel);
  478.     return;
  479.   }
  480.   newchannel = atoi(s);
  481.   if (newchannel < 0 || newchannel > MAXCHANNEL) {
  482.     cp->xmitted += usprintf(cp->fd,cnumber,MAXCHANNEL);
  483.     return;
  484.   }
  485.   if (newchannel == cp->channel) {
  486.     cp->xmitted += usprintf(cp->fd,
  487.       "*** Already on channel %d.\n", cp->channel);
  488.     return;
  489.   }
  490.   send_user_change_msg(cp->name, cp->host, cp->channel, newchannel);
  491.   cp->channel = newchannel;
  492.   cp->xmitted += usprintf(cp->fd, "*** Now on channel %d.\n", cp->channel);
  493.   return;
  494. }
  495.  
  496. static void near
  497. help_command(struct convection *cp)
  498. {
  499.   char *cp1 = getarg(0,1);
  500.  
  501.   if(!(*(cp1))) {
  502.     cp->xmitted += usputs(cp->fd,"Commands may be abbreviated. Commands are:\n"
  503.                                  "/bye           /channel       /exit          /help          /invite\n"
  504.                                  "/links         /msg           /quit          /who           /write\n");
  505.   } else {
  506.     gethelp(IPPORT_CONVERS,cp->fd,cp1);
  507.   }
  508. }
  509.  
  510. static void near
  511. invite_command(struct convection *cp)
  512. {
  513.   char *toname = getarg(0,0);
  514.  
  515.   if (*toname) send_invite_msg(cp->name, toname, cp->channel);
  516. }
  517.  
  518. static void near
  519. links_command(struct convection *cp)
  520. {
  521.   char  tmp[20];
  522.   struct convection *pc;
  523.   struct permlink *pp;
  524.  
  525.   int full = *(getarg(0,0));
  526.  
  527.   cp->xmitted += usprintf(cp->fd,"Host     State         Since%s\n",
  528.     full ? " NextTry Tries Queue Receivd Xmitted" : "");
  529.  
  530.   for(pc = convections; pc; pc = pc->next) {
  531.     if(pc->type == CT_HOST) {
  532.       cp->xmitted += usprintf(cp->fd,
  533.         full ?
  534.         "%-8.8s %-12s %s%15d %7d %7d\n" :
  535.         "%-8.8s %-12s %s\n",
  536.           pc->name,
  537.           "Connected",
  538.           timestring(pc->time),
  539.           0,            /* always 0, cuz NOS handles the tx-queue */
  540.           pc->received,
  541.           pc->xmitted);
  542.     }
  543.   }
  544.   for(pp = Permlink; pp; pp = pp->next) {
  545.     if(!pp->convection || pp->convection->type != CT_HOST) {
  546.       strcpy(tmp,timestring(pp->retrytime)),
  547.       cp->xmitted += usprintf(cp->fd,
  548.         full ?
  549.         "%-8.8s %-12s %s  %s %5d\n" :
  550.         "%-8.8s %-12s %s\n",
  551.           pp->name,
  552.           pp->convection ? "Connecting" : "Disconnected",
  553.           timestring(pp->statetime),
  554.           tmp,
  555.           pp->tries);
  556.     }
  557.   }
  558.   cp->xmitted += usputs(cp->fd,"***\n");
  559.   return;
  560. }
  561.  
  562. static void near
  563. msg_command(struct convection *cp)
  564. {
  565.   struct convection *p;
  566.  
  567.   char *toname = getarg(0,0);
  568.   char *text = getarg(0,1);
  569.  
  570.   if (!*text) return;
  571.   for (p = convections; p; p = p->next)
  572.     if (p->type == CT_USER && !strcmp(p->name, toname))
  573.       break;
  574.   if (!p)
  575.     cp->xmitted += usprintf(cp->fd, "*** No such user: %s.\n", toname);
  576.   else
  577.     send_msg_to_user(cp->name, toname, text);
  578.   return;
  579. }
  580.  
  581. static void near
  582. name_command(struct convection *cp)
  583. {
  584.   int newchannel;
  585.  
  586.   char *s = getarg(0,0);
  587.   if(!*s)
  588.     return;
  589.   sprintf(cp->name,"%.79s",s);
  590.   strlwr(cp->name);
  591.   cp->type = CT_USER;
  592.   sprintf(cp->host,"%.79s",CHostname);
  593.   cp->xmitted += usprintf(cp->fd,
  594.     "conversd @ %s $ Rev: 2.17 (WNOS.5) $ Type /HELP for help.\n", CHostname);
  595.  
  596.   newchannel = atoi(getarg(0,0));
  597.  
  598.   if (newchannel < 0 || newchannel > MAXCHANNEL) {
  599.     cp->xmitted += usprintf(cp->fd,cnumber,MAXCHANNEL);
  600.   } else
  601.     cp->channel = newchannel;
  602.   send_user_change_msg(cp->name, cp->host, -1, cp->channel);
  603.   return;
  604. }
  605.  
  606. static void near
  607. who_command(struct convection *cp)
  608. {
  609.  
  610.   int channel, full = 0, quick = 0;
  611.   struct convection *p;
  612. #ifdef MAILBOX
  613.   struct mbx *m;
  614. #endif
  615.  
  616.   char *buffer = mxallocw(CBUFLEN);
  617.  
  618.   switch(*(getarg(0,0))) {
  619.   case 'l':
  620.     full = 1;
  621.     break;
  622.   case 'q':
  623.     quick = 1;
  624.     break;
  625.   }
  626.  
  627.   if (quick) {
  628.     cp->xmitted += usputs(cp->fd, "Channel Users\n");
  629.     clear_locks();
  630.     do {
  631.       channel = -1;
  632.       for (p = convections; p; p = p->next) {
  633.         if (p->type == CT_USER && !p->locked && (channel < 0 || channel == p->channel)) {
  634.           if (channel < 0) {
  635.             channel = p->channel;
  636.             sprintf(buffer, "%7d", channel);
  637.           }
  638.           strcat(buffer, " ");
  639.           strcat(buffer, p->name);
  640.           p->locked = 1;
  641.         }
  642.       }
  643.       if (channel >= 0) {
  644.         cp->xmitted += usprintf(cp->fd, "%s\n",buffer);
  645.       }
  646.     } while (channel >= 0);
  647.   } else {
  648.     cp->xmitted += usprintf(cp->fd,
  649.       "User     Host     Via      Channel   Time%s\n",
  650.       full ? " HQueue Receivd Xmitted" : "");
  651.     for (p = convections; p; p = p->next) {
  652.       if (p->type == CT_USER) {
  653.         cp->xmitted += usprintf(cp->fd,"%-8.8s %-8.8s %-8.8s %7d %s",
  654.           p->name,
  655.           p->host,
  656.           p->via ? p->via->name : "",
  657.           p->channel,
  658.           timestring(p->time));
  659.         if(full)
  660.           cp->xmitted += usprintf(cp->fd,"%7d %7d %7d",
  661.             0,            /* always 0 cuz NOS handles the tx-queue */
  662.             p->received,
  663.             p->xmitted);
  664.         cp->xmitted += usputs(cp->fd,"\n");
  665.       }
  666.     }
  667.   }
  668. #ifdef MAILBOX
  669.   for(m = Mbox; m != NULLMBX; m = m->next) {
  670.       if(m->state == MBX_CMD) {
  671.         if(quick)
  672.           cp->xmitted += usprintf(cp->fd," LocBBS %s\n",m->name);
  673.         else
  674.           cp->xmitted += usprintf(cp->fd,"%-8s LocBBS@%s\n",m->name,CHostname);
  675.       }
  676.   }
  677. #endif
  678.   cp->xmitted += usputs(cp->fd, "***\n");
  679.   xfree(buffer);
  680.   return;
  681. }
  682.  
  683. static void near
  684. h_cmsg_command(struct convection *cp)
  685. {
  686.   char *name = getarg(0, 0);
  687.   int channel = atoi(getarg(0, 0));
  688.   char *text = getarg(0, 1);
  689.  
  690.   if (*text) send_msg_to_channel(name,channel,text);
  691. }
  692.  
  693. static void near
  694. h_host_command(struct convection *cp)
  695. {
  696.   struct convection *p;
  697.   struct permlink *pp;
  698.  
  699.   char *name = getarg(0,0);
  700.  
  701.   if (!*name) return;
  702.   for (p = convections; p; p = p->next)
  703.     if (!strcmp(p->name, name)) bye_command(p);
  704.   for (pp = Permlink; pp; pp = pp->next)
  705.     if (!strcmp(pp->name, name) && pp->convection && pp->convection != cp)
  706.       bye_command((strcmp(CHostname, name) < 0) ? pp->convection : cp);
  707.   if (cp->type != CT_UNKNOWN) return;
  708.   cp->type = CT_HOST;
  709.   strcpy(cp->name,name);        /* already allocated */
  710.   update_Permlink(name, cp);
  711.   cp->xmitted += usprintf(cp->fd, "/\377\200HOST %s\n", CHostname);
  712.   for (p = convections; p; p = p->next)
  713.     if (p->type == CT_USER) {
  714.       cp->xmitted += usprintf(cp->fd,
  715.         "/\377\200USER %s %s 0 -1 %d\n", p->name, p->host, p->channel);
  716.     }
  717.   return;
  718. }
  719.  
  720. static void near
  721. h_invi_command(struct convection *cp)
  722. {
  723.  
  724.   char *fromname = getarg(0,0);
  725.   char *toname = getarg(0,0);
  726.   int channel = atoi(getarg(0,0));
  727.  
  728.   send_invite_msg(fromname, toname, channel);
  729. }
  730.  
  731. static void near
  732. h_umsg_command(struct convection *cp)
  733. {
  734.  
  735.   char *fromname = getarg(0, 0);
  736.   char *toname = getarg(0, 0);
  737.   char *text = getarg(0, 1);
  738.  
  739.   if (*text) send_msg_to_user(fromname, toname, text);
  740. }
  741.  
  742. static void near
  743. h_user_command(struct convection *cp)
  744. {
  745.   int oldchannel, newchannel;
  746.   struct convection *p;
  747.  
  748.   char *name = getarg(0, 0);
  749.   char *host = getarg(0, 0);
  750.   getarg(0, 0);            /*** ignore this argument, protocol has changed ***/
  751.   oldchannel = atoi(getarg(0, 0));
  752.   newchannel = atoi(getarg(0, 0));
  753.  
  754.   for (p = convections; p; p = p->next)
  755.     if (p->type == CT_USER   &&
  756.     p->channel == oldchannel &&
  757.     p->via == cp             &&
  758.     !strcmp(p->name, name)   &&
  759.     !strcmp(p->host, host))  break;
  760.   if (!p) {
  761.     p = mxallocw(sizeof(struct convection));
  762.     p->type = CT_USER;
  763.     sprintf(p->name,"%.79s",name);
  764.     sprintf(p->host,"%.79s",host);
  765.     p->via = cp;
  766.     p->channel = oldchannel;
  767.     p->time = currtime;
  768.     p->next = convections;
  769.     convections = p;
  770.   }
  771.   if ((p->channel = newchannel) < 0) p->type = CT_CLOSED;
  772.   send_user_change_msg(name, host, oldchannel, newchannel);
  773. }
  774.  
  775. /* Incoming convers session */
  776. void
  777. conv_incom(int s,void *t,void *p)
  778. {
  779.   struct convection *cp;
  780.   struct permlink *pl;
  781.   char *arg;
  782.   int size;
  783.  
  784.   static struct cmdtable {
  785.     char  *name;
  786.     void near (*func) __ARGS((struct convection *cp));
  787.     int  states;
  788.   } cmdtable[] = {
  789.     "?",              help_command,       CM_USER,
  790.     "bye",            bye_command,        CM_USER,
  791.     "channel",        channel_command,    CM_USER,
  792.     "exit",           bye_command,        CM_USER,
  793.     "help",           help_command,       CM_USER,
  794.     "invite",         invite_command,     CM_USER,
  795.     "links",          links_command,      CM_USER,
  796.     "msg",            msg_command,        CM_USER,
  797.     "name",           name_command,       CM_UNKNOWN,
  798.     "quit",           bye_command,        CM_USER,
  799.     "who",            who_command,        CM_USER,
  800.     "write",          msg_command,           CM_USER,
  801.  
  802.     "\377\200cmsg", h_cmsg_command,       CM_HOST,
  803.     "\377\200host", h_host_command,       CM_UNKNOWN,
  804.     "\377\200invi", h_invi_command,       CM_HOST,
  805.     "\377\200umsg", h_umsg_command,       CM_HOST,
  806.     "\377\200user", h_user_command,       CM_HOST,
  807.  
  808.     0, 0, 0,
  809.   };
  810.   struct cmdtable *cmdp;
  811.  
  812.   sockowner(s,Curproc);                /* We own it now */
  813.  
  814.   cp = alloc_connection(s);
  815.  
  816. #ifdef LZW
  817.   if((int)t == 1) {
  818.     lzwinit(s,Lzwbits,Lzwmode);
  819.   }
  820. #endif
  821.  
  822.   for(pl = Permlink; pl; pl = pl->next) {
  823.     if(pl->fd == s) {
  824.       pl->convection = cp;
  825.       if(pl->command != NULLCHAR) {
  826.         usprintf(s,"%s\n",pl->command);
  827.       }
  828.       cp->xmitted += usprintf(s, "/\377\200HOST %s\n", CHostname);
  829.     }
  830.   }
  831.   if(pl == NULLPERMLINK) {
  832.     usputs(cp->fd,"\n*** pse login with '/n <call>'\n\n");
  833.   }
  834.  
  835.   for (; ; ) {
  836. loop:
  837.     if(cp->type == CT_CLOSED) {
  838.       break;
  839.     }
  840.     if((size = recvline(cp->fd,cp->ibuf,CBUFLEN)) <= 0) {
  841.       bye_command(cp);
  842.       break;
  843.     }
  844.     cp->received += size;
  845.     clear_locks();
  846.     cp->locked = 1;
  847.     rip(cp->ibuf);
  848.  
  849.     if(*cp->ibuf == '/') {
  850.         int arglen = strlen(arg = getarg(cp->ibuf + 1, 0));
  851.         for(cmdp = cmdtable; cmdp->name; cmdp++) {
  852.             if(!strnicmp(cmdp->name,arg,arglen)) {
  853.                 if(cmdp->states & (1 << cp->type)) {
  854.                     (*cmdp->func)(cp);
  855.                 }
  856.                 goto loop;
  857.             }
  858.         }
  859.         if(cp->type == CT_USER) {
  860.             cp->xmitted += usprintf(cp->fd,
  861.                 "*** Unknown command '/%s'. Type /HELP for help.\n", arg);
  862.             }
  863.         goto loop;
  864.     }
  865.     if(isprint(*cp->ibuf) != 0 && cp->type == CT_USER) {
  866.       send_msg_to_channel(cp->name, cp->channel, cp->ibuf);
  867.     }
  868.   }
  869.   free_closed_connections();
  870.   return;
  871. }
  872.  
  873.  
  874. #endif /* CONVERS */
  875.